package cate.game.pvp.throne;

import cate.common.table.activity.throne.TBKoRankRow;
import cate.common.table.activity.throne.TBLevelGroupRow;
import cate.common.table.d.GDMail;
import cate.common.table.d.GDOperation;
import cate.common.table.d.GDThrone;
import cate.game.db.facade.KvLoader;
import cate.game.db.mongo.kv.KvMongo;
import cate.game.framework.ModuleMan;
import cate.game.mail.po.MailBuilder;
import cate.game.pvp.throne.data.TBCrossDataHolder;
import cate.game.pvp.throne.data.TBGameKV;
import cate.game.pvp.throne.data.ko.TBKoAdvanceGroup;
import cate.game.pvp.throne.data.ko.TBKoRankItem;
import cate.game.pvp.throne.data.trial.TBTrialRank;
import cate.game.pvp.throne.dto.TBGroupDataDTO;
import cate.game.pvp.throne.msg.*;
import cate.game.role.Role;
import cate.game.role.RoleSimpleBase;
import cate.game.role.mail.Mail;
import cate.game.role.pvp.throne.msg.TBBaseResp;
import cate.game.role.pvp.throne.msg.TBBetInfoNotice;
import cate.game.role.pvp.throne.msg.TBKoCurBetUpdate;
import cate.game.util.IntervalCounter;
import com.google.common.collect.Lists;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

@NoteClass("王座争霸game服数据管理")
public class TBGameDataManager extends ModuleMan {

	@NoteField("游戏服存储的数据")
	public TBGameKV kv;
	
	@NoteField("组服数据持有者")
	public TBCrossDataHolder holder = new TBCrossDataHolder();

	@NoteField("数据已经准备好")
	@Getter
	private boolean dataReady;

	@Override
	public void initDependent() {
		kv = new KvLoader<>(game, TBGameKV.class, KvMongo.KEY_THRONE_BATTLE_GAME).getBySrvId();
	}

	@Override
	public void shutdown() {
		super.shutdown();
		save();
	}


	private final IntervalCounter saveTrigger = new IntervalCounter(3600);

	public void tick() {
		if (saveTrigger.trigger()) {
			save();
		}
	}

	/**
	 * 全量数据同步
	 * @param notice
	 */
	public void syncAllData(TBAllDataNotice notice) {
		log.info("收到来自组服[王座争霸]全量数据同步");
		holder.synAllData(notice);

		boolean firstSyncData = !dataReady;
		boolean seasonChange = checkSeason();
		boolean periodChange = checkPeriod();

		dataReady = true;
		if (firstSyncData || seasonChange || periodChange) {
			game.role.activeForOnline(role -> {
				role.sendNow(new TBBaseResp(game));
				role.getPvp().throne.synData(false);
			});
		}
		checkKoPeriod();
	}

	public void syncPartData(TBPartDataNotice notice){
		holder.syncGroupPart(notice.groupMap);
	}

	public void syncKoBase(TBKoBaseNotice notice){
		holder.syncKoBase(notice.koBase);
		checkKoPeriod();
	}

	public void syncKoBet(TBKoBetNotice notice){
		holder.syncKoBet(notice);
		game.role.activeForOnline(role -> {
			role.sendNow(new TBKoCurBetUpdate(holder.koBase.bet.cur));
		});
	}

	public void syncBoss(TBBossNotice notice){
		holder.syncBoss(notice.boss);
	}

	public List<TBTrialRank> getTrialRank(int group) {
		TBGroupDataDTO groupData = holder.groupMap.get(group);
		if (groupData == null) {
			return new ArrayList<>();
		}
		boolean forceLoad = holder.base.timeTable.inTrial() && System.currentTimeMillis() - groupData.lastTrialUpdateTime >= 5000L;
		if (forceLoad) {
			TBTrialInnerResp resp = game.pvp.throne.message.getTrialData(group);
			groupData.syncTrial(resp.trial);
		}
		return groupData.trial.rankList;
	}

	private boolean checkSeason() {
		boolean change = kv.index != holder.base.season.index;
		if (change) {
			kv.clear();
			kv.index = holder.base.season.index;
			log.info("[王座争霸]游戏服赛季发生变更目前是第[{}]赛季", kv.index);
		}
		return change;
	}

	private boolean checkPeriod() {
		boolean change = kv.period != holder.base.timeTable.period;
		if (change) {
			//修正错误数据
			if (kv.period > holder.base.timeTable.period) {
				kv.period = GDThrone.Period.NULL;
			}
			while (kv.period < holder.base.timeTable.period) {
				kv.period++;
				onPeriodChange(kv.period);
			}
		}
		return change;
	}

	private void checkKoPeriod() {
		final int curRound = holder.koBase.timeTable.getRound();
		final byte curPeriod = holder.koBase.timeTable.getPeriod();
		boolean roundChange = kv.koBase.round != curRound;
		boolean periodChange = kv.koBase.period != curPeriod;
		kv.koBase.update(curRound, curPeriod);
		if (roundChange || periodChange) {
			if (curPeriod == GDThrone.KoPeriod.BET) {
				//通知竞猜
				if (holder.koBase.bet.cur != null) {
					game.role.activeForOnline(role -> {
						TBBetInfoNotice notice = new TBBetInfoNotice(holder.koBase.bet.cur);
						notice.sendNow(role);
					});
				}
			}
			//结算竞猜奖励
			if (curPeriod == GDThrone.KoPeriod.REST) {
				game.role.activeForOnline(role -> {
					role.getPvp().throne.ko.settleBet(false);
				});
				if (curRound >= GDThrone.KO_CHAMPION_ROUND) {
					settleRankRwd();
				}
			}
			//通知阶段变更
			game.role.activeForOnline(role -> {
				role.sendNow(new TBBaseResp(game));
			});
		}
	}

	//阶段变更时
	private void onPeriodChange(byte period){
		log.info("[王座争霸]游戏服阶段发生变更 目前是[{}]", GDThrone.Period.des(period));
//		switch (period){
//			case GDThrone.Period.CHAMPION_BOSS:
//				settleRankRwd();
//				break;
//			default:break;
//		}
	}

	private void settleRankRwd() {
		if (kv.koBase.settleRwd) {
			return;
		}
		kv.koBase.settleRwd = true;
		for (TBGroupDataDTO value : holder.groupMap.values()) {
			//结算排行榜奖励
			handleKoRankRwd(value);
			//结算冠军奖励
			handleChampionRwd(value);
		}
	}

	//结算排行榜奖励
	private void handleKoRankRwd(TBGroupDataDTO value) {
		log.info("[王座争霸]结算淘汰赛排行榜奖励begin");
		for (TBKoAdvanceGroup advGroup : value.ko.advance.groups.values()) {
			final int mailTid = advGroup.groupType == GDThrone.KoGroupType.WINNER ? GDMail.Tid.TB_THRONE_KO_WIN_RANK : GDMail.Tid.TB_THRONE_KO_LOSE_RANK;
			for (int i = 0; i < advGroup.rank.rankList.size(); i++) {
				TBKoRankItem item = advGroup.rank.rankList.get(i);
				if (item.owner.srvId != game.config.srvId) {
					continue;
				}
				Role role = game.role.getRole(item.owner.uid);
				if (role == null) {
					continue;
				}
				final int rank = i + 1;
				role.getPvp().throne.ko.recordRank(value.levelGroup, rank);
				TBKoRankRow rwdRow = game.table.throne.koRankRwd.findRwd(advGroup.groupType, value.levelGroup, rank);
				if (rwdRow != null) {
					Mail mail = new MailBuilder().setRewardConf(rwdRow.rewardStr).setContentId(mailTid).setParamList(Lists.newArrayList(rank)).
							setOperation(GDOperation.THRONE_KO_RANK).build();
					role.getMail().add(mail);
					log.info("[王座争霸][{}]等级组 [{}]类型组 第{}名是{}", value.levelGroup, advGroup.groupType, rank, role.getBase().name);
				}
			}
		}
		log.info("[王座争霸]结算淘汰赛排行榜奖励end");
	}

	//结算冠军奖励
	private void handleChampionRwd(TBGroupDataDTO value) {
		RoleSimpleBase winnerInfo = value.ko.champion.match.getWinnerInfo();
		if (winnerInfo.srvId != game.config.srvId) {
			return;
		}
		TBLevelGroupRow levelGroupRow = game.table.throne.group.get(value.levelGroup);
		if (levelGroupRow == null) {
			return;
		}
		Mail mail = new MailBuilder().setRewardConf(levelGroupRow.championRwdStr).setContentId(GDMail.Tid.TB_THRONE_KO_CHAMPION).setOperation(GDOperation.THRONE_KO_CHAMPION).build();
		game.mail.send(winnerInfo.uid, mail);
		log.info("[王座争霸][{}]组最终冠军是{}", value.levelGroup, winnerInfo.name);
	}
	

	private void save(){
		game.db.kv.save(this.kv);
	}

}
